	package models.entity;


import java.awt.Graphics2D;
import java.util.ArrayList;

import models.Player;
import models.power.Power;
import models.tent.Tent;

//This class have to work following the design pattern "Abstract Factory", in order to create
//all the different entities of the game.
public class Troop extends Entity{
		
	public Troop() {
		super();
		
		//initialize skills
		initSkills();
	}
	
	private void initSkills() {
		
		setStrengh(1);
		setAttackMax(1);
		setAttackMin(1);
		setDefenceMax(0);
		setDefenceMin(0);
		setHealth(200);
		setSpeed(1);
		setRange(1);
		setProbBlow(0.8);
		
		/*moving == 0;
		 * attacking == 1;
		 * death == 2;
		 */
		setCurrentlyStatus(0);
		
	}

	public void move() {
		
		boolean hasAttacked = false;
		
		//The troop is moving
		if(this.getCurrentlyStatus()==0){
			//Checking if the enemy base is near to the Troop
			hasAttacked = attackBase();
			if(!hasAttacked){
				//Checking if is some enemy to attack
				hasAttacked = attack();
				//Checking if there is some Tent to go through
				tentsAction();
				if(!hasAttacked){
					//If the Troop is moving, move it and move its powers
					moveTroop();
					for(Power p:getPowers()){
						p.setPosX(getPosX());
						p.setPosY(getPosY());
					}
				}else{
					setCurrentlyStatus(1);
				}
			}
		
		//The troop is attacking	
		}else if(this.getCurrentlyStatus()==1 && !hasAttacked){
			hasAttacked = this.attackBase();
			if(!hasAttacked){
				hasAttacked = this.attack();
				if(!hasAttacked){
					setCurrentlyStatus(0);
				}
			}			
		//The troop is death	
		}else if(this.getCurrentlyStatus()==2){
			
		}		
		
		update();
	}
	
	private void moveTroop() {
		Player player = getPlayer();
		if(player.color == 1){
			setPosX(getPosX()+getSpeed());
			setInd(getInd()+getSpeed());
			
			if(getInd() >= player.game.stage.tilelong){
				setPosXTile(getPosXTile()+1);
				setInd(0);
			}
			
		}else if(player.color == 2){
			setPosX(getPosX()-getSpeed());
			setInd(getInd()+getSpeed());
			
			if(getInd() >= player.game.stage.tilelong){
				setPosXTile(getPosXTile()-1);
				setInd(0);
			}
		}
	}

	@SuppressWarnings("unchecked")
	private void tentsAction() {
		Player player = this.getPlayer();
		
		ArrayList<Tent> friendlyTents;
		friendlyTents = (ArrayList<Tent>) player.tents.clone();
		for(Tent t:friendlyTents){
			if(this.collideWithTent(t,this.getSpeed())){
				if(this.hasNotPower(t.power)){
					t.power.addAPowerToEntity(this);	
				}
			}
		}
		
	}
	
	@SuppressWarnings("unchecked")
	private boolean attack() {
		
		Player player = getPlayer();
		ArrayList<Entity> enemies = new ArrayList<Entity>();;
		boolean hasAttacked = false;
		
		if(player.color == 1){
			enemies = (ArrayList<Entity>) player.game.player2.entities.clone();
			
		}else if(player.color == 2){
			enemies = (ArrayList<Entity>) player.game.player1.entities.clone();
		}
		
		//First, it looks at the enemies. Case someone collide with this Entity, this one is going to attack, but only once
		for(Entity ent:enemies){
			if(this.collide(ent)){
				if(ent.getCurrentlyStatus()!=2){
					int rndAttack = (int)Math.floor(Math.random()*(getAttackMax()-getAttackMin()+1)+getAttackMin());
					int rndDefence = (int)Math.floor(Math.random()*(ent.getDefenceMax()-ent.getDefenceMin()+1)+ent.getDefenceMin());
					
					if(rndDefence >= rndAttack){
						ent.setHealth(ent.getHealth()-1);
					}else{
						ent.setHealth(ent.getHealth()-rndAttack+rndDefence);
					}
					
					if(ent.getHealth() <= 0){
						//Is dead
						ent.setCurrentlyStatus(2);
					}else{
						if(ent.getCurrentlyStatus()!=1){
							ent.setCurrentlyStatus(1);
						}
					}
					hasAttacked = true;
					break;
				}
			}
		}
		return hasAttacked;
	}

	private boolean attackBase() {
		
		Player player = getPlayer();
		int rndAttack = (int)Math.floor(Math.random()*(getAttackMax()-getAttackMin()+1)+getAttackMin());
		
		if(player.color == 1){
			//2 because of the bases, 1 more because is the last one
			int basePoint = (player.game.stage.size)-(3*player.game.stage.tilelong);
		
			if(getPosX()+player.game.ind>=basePoint||(getPosX()+getSpeed()+player.game.ind>basePoint && getPosX()+player.game.ind<basePoint)){
				
				player.game.player2.health-=rndAttack;
				
				//Is attacking now
				if(getCurrentlyStatus()!=1){
					setCurrentlyStatus(1);
				}
				return true;
				
			}
		}else if(player.color == 2){

			if(getPosX()<=2*player.game.stage.tilelong-player.game.ind){
				
				player.game.player1.health-=rndAttack;
				
				//Is attacking now
				if(getCurrentlyStatus()!=1){
					setCurrentlyStatus(1);
				}
				return true;
			}
		}
		return false;
	}

	@SuppressWarnings("unchecked")
	private boolean hasNotPower(Power power) {
		
		ArrayList<Power> powerList = (ArrayList<Power>) getPowers().clone();
		for(Power p:powerList){
			if(p.equals(power));
			return false;
		}
		return true;
	}

	public void draw(Graphics2D g){
		super.draw(g);
	}
	
	public boolean collide(Troop t){
		return super.collide(t);
	}
	
}
